home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / Ph 1.1.1 / PhClient / mtcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-29  |  13.1 KB  |  466 lines  |  [TEXT/MPS ]

  1. /*_____________________________________________________________________
  2.  
  3.       mtcp.c - MacTCP Interface.
  4. _____________________________________________________________________*/
  5.  
  6. /*_____________________________________________________________________
  7.  
  8.     Header Files.
  9. _____________________________________________________________________*/
  10.  
  11. #pragma load "precompile"
  12. #include <MacTCPCommonTypes.h>
  13. #include <AddressXlation.h>
  14. #include <TCPPB.h>
  15. #include "mtcp.h"
  16. #include "utl.h"
  17. #include "oop.h"
  18. #include "rslv.h"
  19. #include "serv.h"
  20. #include "glob.h"
  21.  
  22. #pragma segment mtcp
  23.  
  24. /*_____________________________________________________________________
  25.  
  26.     Constants.
  27. _____________________________________________________________________*/
  28.  
  29. #define bufferSize        20000            /* size of MacTCP buffer */
  30. #define rcvTimeout        120            /* TCPRcv timeout in seconds */
  31. #define rcvGranularity    100            /* TCPRcv granularity */
  32. #define rcvExpand            1000            /* Response buffer expansion increment */
  33. #define responseLimit    50000            /* Response buffer size limit */
  34.  
  35. /*_____________________________________________________________________
  36.  
  37.     Types.
  38. _____________________________________________________________________*/
  39.  
  40. typedef struct Wds {
  41.     short                len;                /* length of buffer */
  42.     char                *buf;                /* ptr to buffer */
  43.     short                zero;                /* zero terminator */
  44. } Wds;
  45.  
  46. typedef struct ResolverPBlock {
  47.     Boolean                        free;            /* true if block is free (not busy) */
  48.     struct hostInfo            info;            /* MacTCP param block */
  49.     struct ResolverPBlock    *next;        /* pointer to next block in list */
  50. } ResolverPBlock;
  51.  
  52. /*_____________________________________________________________________
  53.  
  54.     Global Variables.
  55. _____________________________________________________________________*/
  56.  
  57. static short                MacTCPDriverRefnum;    /* driver refnum */
  58. static TCPiopb                MacTCPParmBlk;            /* PBControl param block */
  59. static char                    *MacTCPBuffer;            /* ptr to MacTCP buffer */
  60. static StreamPtr            Stream;                    /* ptr to stream, or nil */
  61. static Handle                Response;                /* handle to response buffer */
  62. static Boolean                Connected;                /* true if connected */
  63. static Boolean                Canceled;                /* true if transaction canceled */
  64. static ResolverPBlock    *ResolverPBlockList = nil;    /* ptr to linked list of resolver
  65.                                                                 param blocks */
  66.  
  67. /*_____________________________________________________________________
  68.  
  69.     CheckCancel - Check for User Cancel.
  70.     
  71.     Exit:        function result = true if user cancel.
  72. _____________________________________________________________________*/
  73.  
  74. static Boolean CheckCancel (void)
  75.  
  76. {
  77.     oop_DoEvent(nil, everyEvent, 0, nil);
  78.     return Canceled;
  79. }
  80.  
  81. /*_____________________________________________________________________
  82.  
  83.     mtcp_BeginTransaction - Begin Transaction.
  84. _____________________________________________________________________*/
  85.  
  86. void mtcp_BeginTransaction (void)
  87.  
  88. {
  89.     Canceled = false;
  90. }
  91.  
  92. /*_____________________________________________________________________
  93.  
  94.     mtcp_CancelTransaction - Cancel Transaction.
  95. _____________________________________________________________________*/
  96.  
  97. void mtcp_CancelTransaction (void)
  98.  
  99. {
  100.     Canceled = true;
  101. }
  102.  
  103. /*_____________________________________________________________________
  104.  
  105.     DoPBControl - Make a PBControl Call.
  106.     
  107.     Exit:        function result = error code.
  108. _____________________________________________________________________*/
  109.  
  110. static OSErr DoPBControl (void)
  111.  
  112. {
  113.     PBControl((ParmBlkPtr)&MacTCPParmBlk, true);
  114.     while (MacTCPParmBlk.ioResult == inProgress && !CheckCancel());
  115.     return Canceled ? mtcpCancel : MacTCPParmBlk.ioResult;
  116. }
  117.  
  118. /*_____________________________________________________________________
  119.  
  120.     ResolverResultProc - Resolver Result Proc for Call to StrToAddr
  121. _____________________________________________________________________*/
  122.  
  123. static pascal void ResolverResultProc (struct hostInfo *hostInfoPtr, 
  124.     char *userDataPtr)
  125.  
  126. {
  127. #pragma unused (hostInfoPtr)
  128.     
  129.     *userDataPtr = true;
  130. }
  131.  
  132. /*_____________________________________________________________________
  133.  
  134.     InitMacTCPParmBlk - Initialize MacTCP PBControl Parameter Block.
  135.  
  136.     Entry:    pBlock = pointer to param block.
  137.                 csCode = code for type of call.
  138.  
  139.     Exit:        MacTCPParmBlk initialized.    
  140. _____________________________________________________________________*/
  141.  
  142. static void InitMacTCPParmBlk (TCPiopb *pBlock, short csCode)
  143.  
  144. {
  145.     memset(pBlock, 0, sizeof(TCPiopb));
  146.     pBlock->ioCRefNum = MacTCPDriverRefnum;
  147.     pBlock->csCode = csCode;
  148.     pBlock->tcpStream = Stream;
  149. }
  150.  
  151. /*_____________________________________________________________________
  152.  
  153.     mtcp_Initialize - Initialize MacTCP.
  154. _____________________________________________________________________*/
  155.  
  156. #pragma segment init
  157.  
  158. OSErr mtcp_Initialize (void)
  159.  
  160. {
  161.     OSErr            rCode;            /* result code */
  162.  
  163.     MacTCPBuffer = NewPtr(bufferSize);
  164.     if (!MacTCPBuffer) return MemError();
  165.     if (rCode = OpenDriver("\p.IPP", &MacTCPDriverRefnum)) return rCode;
  166.     if (rCode = OpenResolver(nil)) return rCode;
  167.     /*return rslv_Init(MacTCPDriverRefnum);*/
  168.     return noErr;
  169. }
  170.  
  171. #pragma segment mtcp
  172.  
  173. /*_____________________________________________________________________
  174.  
  175.     mtcp_Terminate - Terminate MacTCP.
  176. _____________________________________________________________________*/
  177.  
  178. OSErr mtcp_Terminate (void)
  179.  
  180. {
  181.     ResolverPBlock        *pBlock;            /* pointer to resolver param block */
  182.     
  183.     pBlock = ResolverPBlockList;
  184.     while (pBlock) {
  185.         while (!pBlock->free);
  186.         pBlock = pBlock->next;
  187.     }
  188.     return CloseResolver();
  189. }
  190.  
  191. /*_____________________________________________________________________
  192.  
  193.     mtcp_OpenConnection - Open Connection to Ph Server.
  194.     
  195.     Entry:    host = Ph server host domain name.
  196.     
  197.     Exit:        function result = error code.
  198.                 if no errors:
  199.                     Stream = pointer to created TCP stream.
  200.                     Connected = true.
  201. _____________________________________________________________________*/
  202.  
  203. OSErr mtcp_OpenConnection (char *host)
  204.  
  205. {
  206.     OSErr                    rCode;            /* result code */
  207.     unsigned long        ipAddr;            /* ip address of host */
  208.     Str255                server;            /* server domain name */
  209.     ResolverPBlock        *pBlock;            /* ptr to resolver param block */
  210.     short                    nTry;                /* number of times to try MacTCP resolver */
  211.     
  212.     Stream = nil;
  213.     Connected = false;
  214.     utl_CopyPString(server, host);
  215.     p2cstr(server);
  216.     nTry = 2;
  217.     while (true) {
  218.         pBlock = ResolverPBlockList;
  219.         while (pBlock && !pBlock->free) pBlock = pBlock->next;
  220.         if (!pBlock) {
  221.             pBlock = (ResolverPBlock*)NewPtr(sizeof(ResolverPBlock));
  222.             pBlock->next = ResolverPBlockList;
  223.             ResolverPBlockList = pBlock;
  224.         }
  225.         pBlock->free = false;
  226.         rCode = StrToAddr(server, &pBlock->info, ResolverResultProc, &pBlock->free);
  227.         if (rCode == cacheFault) {
  228.             while (!pBlock->free && !CheckCancel());
  229.         } else {
  230.             pBlock->free = true;
  231.             if (rCode) return rCode;
  232.         }
  233.         if (Canceled) return mtcpCancel;
  234.         rCode = pBlock->info.rtnCode;
  235.         if (rCode == cacheFault || rCode == outOfMemory) {
  236.             /* handle problem with MacTCP resolver - error code is
  237.                 still set to cacheFault (MacTCP v1.0.1) or outOfMemory
  238.                 (MacTCP v1.1) after result proc has been called! In this 
  239.                 case, first try closing and reopening the MacTCP resolver 
  240.                 and try it again. If it fails again, give up and call my 
  241.                 own resolver. */
  242.             if (--nTry) {
  243.                 if (rCode = CloseResolver()) return rCode;
  244.                 if (rCode = OpenResolver(nil)) return rCode;
  245.                 continue;
  246.             }
  247.             /*if (rCode = rslv_Resolve(host, CheckCancel, &ipAddr))
  248.                 return Canceled ? mtcpCancel : rCode;*/
  249.             return rCode;
  250.             break;
  251.         } else if (rCode) {
  252.             return rCode;
  253.         } else {
  254.             ipAddr = pBlock->info.addr[0];
  255.             break;
  256.         }
  257.     }
  258.     InitMacTCPParmBlk(&MacTCPParmBlk, TCPCreate);
  259.     MacTCPParmBlk.csParam.create.rcvBuff = MacTCPBuffer;
  260.     MacTCPParmBlk.csParam.create.rcvBuffLen = bufferSize;
  261.     if (rCode = DoPBControl()) return rCode;
  262.     Stream = MacTCPParmBlk.tcpStream;
  263.     InitMacTCPParmBlk(&MacTCPParmBlk, TCPActiveOpen);
  264.     MacTCPParmBlk.csParam.open.remoteHost = ipAddr;
  265.     MacTCPParmBlk.csParam.open.remotePort = PhPort;
  266.     if (rCode = DoPBControl()) return rCode;
  267.     Connected = true;
  268.     return noErr;
  269. }
  270.  
  271. /*_____________________________________________________________________
  272.  
  273.     mtcp_CloseConnection - Close Ph Server Connection.
  274.     
  275.     Exit:        function result = error code.
  276.                 Connection closed and stream released.
  277.                 Connected = false.
  278.                 Stream = nil.
  279. _____________________________________________________________________*/
  280.  
  281. OSErr mtcp_CloseConnection (void)
  282.  
  283. {
  284.     OSErr            rCodeClose;            /* TCPClose result code */
  285.     OSErr            rCodeRelease;        /* Release result code */
  286.     TCPiopb        releaseBlock;        /* Release param block */
  287.  
  288.     rCodeClose = rCodeRelease = noErr;
  289.     if (Connected) {
  290.         InitMacTCPParmBlk(&MacTCPParmBlk, TCPClose);
  291.         rCodeClose = DoPBControl();
  292.         Connected = false;
  293.     }
  294.     if (Stream) {
  295.         InitMacTCPParmBlk(&releaseBlock, TCPRelease);
  296.         rCodeRelease = PBControl((ParmBlkPtr)&releaseBlock, false);
  297.         Stream = nil;
  298.     }
  299.     if (rCodeClose) return rCodeClose;
  300.     return rCodeRelease;
  301. }
  302.  
  303. /*_____________________________________________________________________
  304.  
  305.     mtcp_AbortConnection - Abort Ph Server Connection.
  306.     
  307.     Exit:        function result = error code.
  308.                 Connection aborted and stream released.
  309.                 Connected = false.
  310.                 Stream = nil.
  311. _____________________________________________________________________*/
  312.  
  313. OSErr mtcp_AbortConnection (void)
  314.  
  315. {
  316.     OSErr            rCodeAbort;            /* TCPAbort result code */
  317.     OSErr            rCodeRelease;        /* Release result code */
  318.     TCPiopb        abortBlock;            /* Abort param block */
  319.     TCPiopb        releaseBlock;        /* Release param block */
  320.  
  321.     rCodeAbort = rCodeRelease = noErr;
  322.     if (Connected) {
  323.         InitMacTCPParmBlk(&abortBlock, TCPAbort);
  324.         rCodeAbort = PBControl((ParmBlkPtr)&abortBlock, false);
  325.         Connected = false;
  326.     }
  327.     if (Stream) {
  328.         InitMacTCPParmBlk(&releaseBlock, TCPRelease);
  329.         rCodeRelease = PBControl((ParmBlkPtr)&releaseBlock, false);
  330.         Stream = nil;
  331.     }
  332.     if (rCodeAbort) return rCodeAbort;
  333.     return rCodeRelease;
  334. }
  335.  
  336. /*_____________________________________________________________________
  337.  
  338.     mtcp_PhCommand - Execute a Ph Server Command.
  339.     
  340.     Entry:    command = handle to command string, terminated by a line feed.
  341.                 response = handle to allocated response buffer.
  342.                 
  343.     Exit:        function result = error code.
  344.                 response = handle to response.
  345.                 truncated = true if reponse truncated.
  346.                     
  347.     The response memory block size in increased if necessary to hold the
  348.     full response, up to a limit of responseLimit bytes.
  349.     
  350.     The response block contains a leading line feed character, followed
  351.     by the response text exactly as received from the server, followed by
  352.     a zero byte.
  353.     
  354.     Any carriage return characters in the response block are stripped out.
  355. _____________________________________________________________________*/
  356.  
  357. OSErr mtcp_PhCommand (Handle command, Handle response,
  358.     Boolean *truncated)
  359.  
  360. {
  361.     Wds            wds;                            /* MacTCP wds */
  362.     long            responseSize;                /* size of response buffer */
  363.     long            next;                            /* index in response of next char to read */
  364.     short            ct;                            /* timeout counter */
  365.     char            *p;                            /* pointer into string */
  366.     char            *q;                            /* pointer into string */
  367.     char            *r;                            /* pointer into string */
  368.     long            n;                                /* number of chars read */
  369.     Boolean        done;                            /* true when entire response received */
  370.     short            code;                            /* server response code */
  371.     short            len;                            /* length of database off message */
  372.     OSErr            rCodeSend;                    /* send result code */
  373.     OSErr            rCodeRcv;                    /* receive result code */
  374.     
  375.     *DbOffMsg = 0;
  376.     HLock(command);
  377.     p = *command;
  378.     q = strchr(p, '\r');
  379.     wds.len = q-p+1;
  380.     wds.buf = p;
  381.     wds.zero = 0;
  382.     InitMacTCPParmBlk(&MacTCPParmBlk, TCPSend);
  383.     MacTCPParmBlk.csParam.send.wdsPtr = (Ptr)&wds;
  384.     rCodeSend = DoPBControl();
  385.     HUnlock(command);
  386.     if (rCodeSend && rCodeSend != connectionTerminated && 
  387.         rCodeSend != connectionClosing) return rCodeSend;
  388.     responseSize = GetHandleSize(response);
  389.     next = 1;
  390.     **response = '\r';
  391.     HLock(response);
  392.     done = false;
  393.     ct = rcvTimeout;
  394.     *truncated = false;
  395.     rCodeRcv = noErr;
  396.     while (!done && ct--) {
  397.         if (next + rcvGranularity + 1 > responseSize) {
  398.             if (responseSize < responseLimit) {
  399.                 responseSize += rcvExpand;
  400.             } else {
  401.                 responseSize = responseLimit + rcvGranularity;
  402.                 next = responseLimit;
  403.             }
  404.             HUnlock(response);
  405.             SetHandleSize(response, responseSize);
  406.             HLock(response);
  407.         }
  408.         p = *response + next;
  409.         InitMacTCPParmBlk(&MacTCPParmBlk, TCPRcv);
  410.         MacTCPParmBlk.csParam.receive.commandTimeoutValue = 1;
  411.         MacTCPParmBlk.csParam.receive.rcvBuff = p;
  412.         MacTCPParmBlk.csParam.receive.rcvBuffLen = rcvGranularity;
  413.         rCodeRcv = DoPBControl();
  414.         if (rCodeRcv == commandTimeout) continue;
  415.         if (rCodeRcv) break;
  416.         ct = rcvTimeout;
  417.         n = MacTCPParmBlk.csParam.receive.rcvBuffLen;
  418.         q = p + n - 1;
  419.         r = q;
  420.         if (*r == '\r') {
  421.             while (--r >= *response) {
  422.                 if (*r == '\r') {
  423.                     r++;
  424.                     code = atoi(r);
  425.                     done = code >= 200;
  426.                     if (code == phDatabaseOff) {
  427.                         r = strpbrk(r, ":\r");
  428.                         if (*r == ':') {
  429.                             r++;
  430.                             r += strspn(r, " \t");
  431.                         }
  432.                         len = q-r;
  433.                         if (len > 255) len = 255;
  434.                         memcpy(DbOffMsg+1, r, len);
  435.                         *DbOffMsg = len;
  436.                         rCodeRcv = connectionTerminated;
  437.                     }
  438.                     break;
  439.                 }
  440.             }
  441.         }
  442.         next += n;
  443.     }
  444.     if (!done) {
  445.         if (!rCodeRcv) rCodeRcv = commandTimeout;
  446.         HUnlock(response);
  447.         SetHandleSize(response, 1);
  448.         **response = 0;
  449.         return rCodeRcv;
  450.     }
  451.     if (*truncated = next >= responseLimit) {
  452.         next = responseLimit - 1;
  453.         *(*response + next - 1) = '\r';
  454.     }
  455.     *(*response + next) = 0;
  456.     p = *response;
  457.     q = *response;
  458.     while (*p) {
  459.         if (*p != '\n') *q++ = *p;
  460.         p++;
  461.     }
  462.     *q = 0;
  463.     HUnlock(response);
  464.     return rCodeSend ? rCodeSend : rCodeRcv;
  465. }
  466.